package ws.utils.jdbc;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * This class owns some common JDBC settings for setting up a DB connection.
 * 
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public class DBConnection {

  /** JDBC driver used. */
  public static final String Driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
  /** Database connection. */
  private static Connection dbCon = null;
  /** Url to make the connection. */
  static String dbUrl = "jdbc:sqlserver://goldberg-wm:1433;"
          + "databaseName=PerformanceTest;user=sa;password=sg4765j;";
  /**
   * Flag that tells if we are working connected to the database (online)
   * or disconnected (offline).
   */
  public static boolean online = false;
  private final static DBConnection dbsettings = new DBConnection();

  /**
   * Establish one connection using the URL, {@code dbUrl}.
   *
   * @return the connection.
   *
   * @throws SQLException
   */
  public static Connection getDBCon() throws SQLException {
    synchronized (dbsettings) {
      if (dbCon == null || dbCon.isClosed()) {
        dbCon = DriverManager.getConnection(dbUrl);
        System.out.println("Connection established!");
        dbsettings.notifyAll();
      }
      return dbCon;
    }
  }

  /**
   * Close the established database connection.
   * 
   * @throws SQLException
   */
  public static void closeDBCon() throws SQLException {
    synchronized (dbsettings) {
      if (isOnline()) {
        dbCon.close();
        dbsettings.notifyAll();
        System.out.println("Database connection closed!");
      }
    }
  }

  /**
   * Check if there is one open connection with the database server.
   *
   * @return {@code true} if there is one open connection with the server,
   *         {@code false} otherwise.
   *
   * @throws SQLException
   */
  public static synchronized boolean isOnline() throws SQLException {
    return dbCon != null && !dbCon.isClosed();
  }

  /**
   * Wait for changes on the object state.
   *
   * @throws InterruptedException
   */
  public static void waitForChanges() throws InterruptedException {
    synchronized (dbsettings) {
      dbsettings.wait();
    }
  }

  /**
   * Set the URL for the JDBC driver used to connect to the database using
   * <b>SQL Authentication</b>.
   *
   * <p>
   * Each driver has its own URL format, so this method finds the first
   * format that the driver accepts.
   * </p>
   *
   *
   * @param driver JDBC driver selected to connect to the database.
   * @param server name of the server where the database is.
   * @param database name of the database to connect to.
   * @param port port that the server is listening to.
   * @param username login credential.
   * @param password login credential.
   *
   * @return return {@code true} if the URL was set, which means that a
   *                Driver that accepts that URL was found, return {@code false}
   *                otherwise.
   */
  public static boolean setDBUrl(Driver driver, String server, String port, String database, String username, String password) throws SQLException {
    String url = "jdbc:sqlserver://"
            + server + ":"
            + port + ";"
            + "databaseName=" + database + ";"
            + "user=" + username + ";"
            + "password=" + password + ";";
    if (driver.acceptsURL(url)) {
      dbUrl = url;
      return true;
    } else {
      return false;
    }
  }

  /**
   * Set the URL for the JDBC driver used to connect to the database using
   * <b>Windows Authentication/b>.
   *
   * <p>
   * Each driver has its own URL format, so this method finds the first
   * format that the driver accepts.
   * </p>
   *
   *
   * @param driver JDBC driver selected to connect to the database.
   * @param server name of the server where the database is.
   * @param database name of the database to connect to.
   * @param port port that the server is listening to.
   *
   * @return return {@code true} if the URL was set, which means that a
   *                Driver that accepts that URL was found, return {@code false}
   *                otherwise.
   */
  public static boolean setDBUrl(Driver driver, String server, String port, String database) throws SQLException {
    String url = "jdbc:sqlserver://"
            + server + ":"
            + port + ";"
            + "databaseName=" + database + ";"
            + "integratedSecurity=true;";
    if (driver.acceptsURL(url)) {
      dbUrl = url;
      return true;
    } else {
      return false;
    }
  }

  /**
   * Url to make the connection.
   *
   * @return Url to make the connection.
   */
  public static String getDBUrl() {
    return dbUrl;
  }
}
